﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Web;

namespace LINQToolKit.Web
{
    public class HttpRequest : IRequest
    {
        public string ContentType { get; set; }

        private Encoding _encoding;

        public HttpRequest()
        {
            this.ContentType = "application/xml";
            this._encoding = Encoding.UTF8;
        }

        public HttpRequest(Encoding encoding)
        {
            this._encoding = encoding;
        }

        public Encoding Encoding
        {
            get 
            {
                return this._encoding;
            }
            set { this._encoding = value; }
        }

        protected virtual HttpWebRequest CreateRequest(
            Uri requestUrl, string httpMethod, string post, IDictionary<string, string> headers)
        {
            var request = (HttpWebRequest)WebRequest.Create(requestUrl);
            request.Method = httpMethod;
            request.ContentType = this.ContentType;

            if (headers != null)
            {
                foreach (var key in headers.Keys)
                {
                    request.Headers.Add(key, headers[key]);
                }
            }

            if (string.IsNullOrEmpty(post))
            {
                request.ContentLength = 0;
            }
            else
            {
                byte[] buffer = this.FormatPost(post);
                request.ContentLength = buffer.Length;
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(buffer, 0, buffer.Length);
                requestStream.Close();
            }

            return request;
        }

        protected virtual byte[] FormatPost(string post)
        {
            Encoding encoding = 
                (this.Encoding == null) ? Encoding.UTF8 : this.Encoding;
            return encoding.GetBytes(post);
        }

        public void Dispose()
        {
            // do nothing
        }

        public RequestResult Execute(Uri requestUrl, string httpMethod, string post)
        {
            requestUrl.AssertNull("requestUrl");
            httpMethod.AssertNull("httpMethod");
            var result = new RequestResult();
            result.RequestUrl = requestUrl;

            try
            {
                var request = this.CreateRequest(requestUrl, httpMethod, post, null);
                var response = (HttpWebResponse)request.GetResponse();
                var stream = new StreamReader(response.GetResponseStream(), this.Encoding);
                result.Message = stream.ReadToEnd();
                result.StatusCode = (int)response.StatusCode;
                stream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                result.Error = ex;
                result.Message = ex.Message;
            }

            return result;
        }
    }
}